/*******************************************************************************
 * @file fdt_shmmgr.h
 * @brief  inter process Fast Data Transfer
 *
 *
 * Author: Kevinx
 *
 * Copyright (c) 2015 Kevinx. All Rights Reserved.
 *
 * CONFIDENTIALITY AND LIMITED USE
 *
 * This software, including any software of third parties embodied herein,
 * contains information and concepts which are confidential to Kevinx
 * and such third parties. This software is licensed for use
 * solely in accordance with the terms and conditions of the applicable
 * license agreement with Kevinx or its authorized distributor.
 ************************************************************************************/
#ifndef __SHM_AREA_H__
#define __SHM_AREA_H__
#include <stdint.h>
#include <endian.h>
#include "cyclic_list.h"

typedef unsigned long ulong_t;
typedef unsigned long address_t;

#define address_to_ptr(addr) ((void*)((address_t)(addr)))
#define ptr_to_address(ptr) ((address_t)(ptr))

#define BITS_PER_BYTE 8
#define BITS_PER_LONG (BITS_PER_BYTE*sizeof(ulong_t))
#define BITOP_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
#define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)

union fdt_buf_ptr {
    void* ptr;
    address_t addr;
    struct {
#if __BYTE_ORDER == __LITTLE_ENDIAN 
        address_t offset: 26;       
        address_t id: 6;
#else
        address_t id: 6;
        address_t offset: 26;        
#endif        
    } s;
};

struct fdt_buffer {
    union fdt_buf_ptr packet_ptr;
    ulong_t len;
};

#define ARRAY_SIZE(ARR) (sizeof(ARR)/sizeof(ARR[0]))
#define BYTES_TO_COUNT(bytes) (bytes/(2*sizeof(ulong_t)))
#define COUNT_TO_BYTES(cnt) (cnt*2*sizeof(ulong_t))

struct shm_area_struct
{
    address_t start_addr;
    address_t end_addr;
    uint32_t size;

    int flags;

    struct list_head list;
    ulong_t bits[0];
};

struct fdt_shmmgr
{
    struct shm_area_struct* mbuf_area;
    struct list_head mbuf_list;
    int m_count;

#if 0
    //struct shm_area_struct* ref_areas ;
    struct list_head list;
    struct shm_area_struct* shma_cache;

    struct list_head ch_list;
#endif    
};

/*
 * fdt_shmmgr_create:
 *  create shared memory pool manager object
 *  @id: 
 *  @size: shared memory pool size
 *  
 *  @return: 0 - success, -1 - failed
 */
int fdt_shmmgr_create(struct fdt_shmmgr* shmmgr, const char* id, uint32_t size);

/*
 * fdt_shmmgr_destory:
 *  destory shared memory pool manager object
 * 
 * @return: 0 - success, -1 - failed
 */
int fdt_shmmgr_destory(struct fdt_shmmgr* shmmgr);

/*
 * fdt_shmmgr_alloc:
 *  allocate a buffer from shmmgr's pool
 *
 * @return: buffer address - success, NULL - failed
 */
void* fdt_shmmgr_alloc(struct fdt_shmmgr* shmmgr);

/*
 * fdt_shmmgr_alloc_with_backoff:
 *  allocate a buffer from shmmgr's pool, with 128 bytes headroom before 
 *
 * @return: buffer address - success, NULL - failed
 */
void* fdt_shmmgr_alloc_with_backoff(struct fdt_shmmgr* shmmgr);

/*
 * fdt_shmmgr_free: 
 *  free a buffer to shmmgr's pool, or
 *  if buffer belongs to counterpart, return it;
 *  otherwise, do nothing
 */
void fdt_shmmgr_free(struct fdt_shmmgr* shmmgr, void* p);

/*
 * fdt_shmmgr_mbuf_number:
 *  get free buffer number in shmmgr's pool
 *
 * @return: number of buffer
 */
int fdt_shmmgr_mbuf_number(struct fdt_shmmgr* shmmgr);

/*
 * fdt_shmmgr_attach_shma:
 *  create a shm_area_struct object and attaches the shared memory segment identified  by id
 *
 * @return: shm_area_struct obj address - success, NULL - failed
 */
struct shm_area_struct* fdt_shmmgr_attach_shma(const char* id, uint32_t size);

/*
 * fdt_shmmgr_del_shma:
 *  delete a shm_area_struct object and deattaches the shared memory segment in it
 *
 * @return: 0 - success, -1 - failed
 */
int fdt_shmmgr_del_shma(struct shm_area_struct* shma);

#endif /*__SHM_AREA_H__*/
